#pragma	once

#include "ZOdbcPrerequisite.h"
#include "ZPoolObject.h"
#include <sql.h>
#include <sqlext.h>
#include <vector>
#include <boost/shared_ptr.hpp>

namespace	Z	{

class	Stream;

namespace	Odbc	{

//------------------------------------------------------------------------------------------------------------------------
class	_ZOdbcApi	Recordset
	:	public PoolObject
{
private:
	//------------------------------------------------------------------------------------------------------------------------
	class	_ZOdbcApi	Column	{
	public:
		//------------------------------------------------------------------------------------------------------------------------
		class	Exception	{
			public:	const	std::string	getColName()	const	{	return mColName;	}
			protected:	Exception(const std::string& colName)	:	mColName(colName)	{}
			private:	std::string	mColName;
		};
		class	NotFound	:	public Exception	{
			public:	NotFound(const std::string colName)	:	Exception(colName)	{}
		};
		class	NullData:	public Exception	{
			public:	NullData(const std::string colName)	:	Exception(colName)	{}
		};
	public:
		Column();
		Column(Connection& kConnection);
		~Column();
		char*	colBuf()	const	{	return mColBuf;	}
		SQLCHAR*	colName()	const	{	return mColName;	}
		bool	isNullData()	const	{	return mNullData;	}
		void	setNullData(bool isNullData)	{	mNullData	= isNullData;	}
	public:
		static	const	SQLINTEGER	colBufSize	= 8192;
		static	const	SQLSMALLINT	colNameSize	= 64;
	private:
		char*	mColBuf;
		SQLCHAR*	mColName;
		bool	mNullData;
	};

public:
	Recordset(Connection& kConnection);
	~Recordset();
	SQLHSTMT	stmt()	const	{	return mStmt;	}
	bool	fetch();
	bool	moreResults();
	void	bind();
	const	Column*	findColumn(const std::string& colName)	const;
	int	getInt(const std::string& colName)	const;
	__int64	getInt64(const std::string& colName)	const;
	float	getFloat(const std::string& colName)	const;
	char	getChar(const std::string& colName)	const;
	std::string	getString(const std::string& colName)	const;
	Stream		getStream(const std::string& colName)	const;

private:
	void	unbind();
	static	void	verify(const Column* pColumn, const std::string& colName);

private:
	SQLHSTMT	mStmt;
	Connection&	mConnection;
	SQLSMALLINT	mNumResultCols;
	bool	mBound;
	typedef	std::vector<Column>	Columns;
	Columns	mColumns;
};

}

}